package com.net.core.core.sql;


import lombok.Data;

import java.lang.reflect.Field;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

@Data
public class ObjReflect<T> {

    Class<T> clazz;
    String tableName;

    /**
     * String 是 数据库的 字段名 key 都是小写
     */
    Map<String, Field> tableIds = new HashMap<>();
    /**
     * 没有id的属性 key 都是小写
     */
    Map<String, Field> fields = new HashMap<>();
    /**
     * 所有属性 key 都是小写
     */
    Map<String, Field> fieldAll = new HashMap<>();
    /**
     * 通过属性名称 找到数据库名称 key 都是小写
     */
    Map<String, String> culmMap = new HashMap<>();

    public ObjReflect(Class<T> clz) {
        clazz = clz;
        priseFields(clz);
        tableName = priseTableName(clz);
    }

    public ObjReflect(T t) {
        this((Class<T>) t.getClass());
    }

    private static Calendar calendar = Calendar.getInstance();

    public String priseTableName(Class clz) {
        TableName annotation = (TableName) clz.getAnnotation(TableName.class);
        String tableName = null;
        if (annotation != null) {
            tableName = annotation.value();
        } else if (tableName == null) {
            tableName = clz.getSimpleName();
        }
        if (tableName.indexOf(".") != -1) {
            String s = tableName.substring(0, tableName.indexOf(".")) + ".";
            s += tableName.substring(tableName.lastIndexOf("."));
            tableName = s;
        }
        return tableName;
    }

    private void priseFields(Class clz) {
        for (Field curField : clz.getDeclaredFields()) {
            String key = null;
            TableId annoId = curField.getAnnotation(TableId.class);
            if (annoId != null) {
                key = annoId.value();
                key = getFieldName(key, curField);
                tableIds.put(key.toLowerCase(), curField);
                fieldAll.put(key.toLowerCase(), curField);
                continue;
            }
            TableField annotation = curField.getAnnotation(TableField.class);
            if (annotation != null) {
                //如果数据库不适用该字段，跳出
                if (!annotation.exist()) {
                    continue;
                }
                key = annotation.value();
            }
            key = getFieldName(key, curField);
            fields.put(key.toLowerCase(), curField);
            fieldAll.put(key.toLowerCase(), curField);
        }
    }

    private String getFieldName(String key, Field curField) {
        String name = curField.getName();
        if (key == null || key.length() == 0) {
            key = name;
        } else {
            culmMap.put(name, key);
        }
        return key;
    }

    public String getFieldName(String key) {
        String s = culmMap.get(key);
        if (s != null) {
            key = s;
        }
        return key;
    }

    /**
     * 获取数据库自动名称
     *
     * @param key
     * @return
     */
    public String getFiledName(String key) {
        String clumName = culmMap.get(key);
        return clumName == null ? key : clumName;
    }

    /***
     *  下划线转驼峰
     * @param para
     * 驼峰命名的字符串
     */
    public static String underlineToHump(String para) {
        StringBuilder result = new StringBuilder();
        String a[] = para.split("_");
        for (String s : a) {
            if (!para.contains("_")) {
                result.append(s);
                continue;
            }
            if (result.length() == 0) {
                result.append(s.toLowerCase());
            } else {
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }


    public T newInstance(Map<String, Object> map) throws Exception {
        T t = clazz.newInstance();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Field field = fields.get(entry.getKey().toLowerCase());
            if (field != null) {
                field.setAccessible(true);
                //判断是否存在注解
                if (field.getType().equals(String.class)) {
                    field.set(t, entry.getValue().toString());
                } else {
                    field.set(t, entry.getValue());
                }
            }
        }
        return t;
    }


}

